package com.sgl.gk.controller;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.sg.comm.common.Ret;
import com.sg.comm.opcuav2.NodeDTOV2;
import com.sg.comm.opcuav2.OpcUaReadReqV2;
import com.sg.comm.opcuav2.OpcUaWriteReqV2;
import com.sg.comm.opcuav2.batch.BatchReadDTO;
import com.sg.comm.service.OpcUaServiceV2;
import com.sgl.common.core.domain.AjaxResult;
import com.sgl.gk.domain.*;
import com.sgl.gk.mapper.GkSignalCommunicationMapper;
import com.sgl.gk.scheduled.ScheduledTask;
import com.sgl.gk.scheduled.vo.ServiceData;
import com.sgl.gk.scheduled.vo.SocketDataVo;
import com.sgl.gk.service.GkSignalCommunicationService;
import com.sgl.gk.service.GkStatisticsService;
import com.sgl.gk.tools.OpcUATool;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author:xec
 * @date:2022/11/17 9:25
 **/
@RestController
@Slf4j
@RequestMapping("/gk/statistics")
public class GkStatisticsController {

    @Autowired
    GkStatisticsService gkStatisticsService;

    @Autowired
    GkSignalCommunicationService gkSignalCommunicationService;

    @DubboReference(version = "1.0.0", url = "dubbo://127.0.0.1:20880", check = false)
    private OpcUaServiceV2 opcUaServiceV2;

    @Value("${communication.mode}")
    public String communication;

    @GetMapping("/plcInfos")
    public AjaxResult plcInfos(){
        List<GkSignalCommunication> list = gkSignalCommunicationService.list(null);
        return AjaxResult.success(list);
    }

    @GetMapping("/dataStatisticsInfos")
    public AjaxResult dataStatisticsInfos(){
        return gkStatisticsService.dataStatisticsInfos();
    }

    /**
     * 大屏工位数据获取
     * @return
     */
    @GetMapping("/stationData")
    public AjaxResult stationData(){
        return gkStatisticsService.stationData();
    }

    /**
     * 获取大屏工位合格率与完成率
     * @return
     */
    @GetMapping("/getOkAndCompleteRate")
    public AjaxResult getOkAndCompleteRate(){
        return gkStatisticsService.getOKAndCompleteRate();
    }

    /**
     * 每小时产量获取
     * @return
     */
    @GetMapping("/getCompleteCntByTime")
    public AjaxResult getCompleteCntByTime(){
        return gkStatisticsService.getCompleteCntByTime();
    }

    /**
     * 看版配置获取工位数据接口
     * @return
     */
    @GetMapping("/stationAllInfo")
    public AjaxResult stationAllInfo(){
        return gkStatisticsService.stationAllInfo();
    }

    /**
     * 批量修改工位数据信息接口
     * @param gkShowStationInfoList
     * @return
     */
    @PostMapping("/editStationInfo")
    public AjaxResult editStationInfo(@RequestBody List<GkShowStationInfo> gkShowStationInfoList){
        return gkStatisticsService.editStationInfo(gkShowStationInfoList);
    }


    /**
     * 大屏产线信息获取
     * @return
     */
    @GetMapping("/productionLineInfo")
    public AjaxResult productionLineInfo(){
        return gkStatisticsService.productionLineInfo();
    }

    /**
     * 所有产线信息获取
     * @return
     */
    @GetMapping("/productionLineAllInfo")
    public AjaxResult productionLineAllInfo(){
        return gkStatisticsService.productionLineAllInfo();
    }

    /**
     * 修改产线信息
     * @param gkReservedInfoList
     * @return
     */
    @PostMapping("/editProductionLineInfo")
    public AjaxResult editProductionLineInfo(@RequestBody List<GkReservedInfo> gkReservedInfoList){
        return gkStatisticsService.editProductionLineInfo(gkReservedInfoList);
    }

    /**
     * 看版设置信息获取
     * @return
     */
    @GetMapping("/dailyPlanned")
    public AjaxResult dailyPlanned(){
        return gkStatisticsService.dailyPlanned();
    }

    /**
     * 看版设置信息修改
     * @param gkSetting
     * @return
     */
    @PutMapping("/updateDailyPlanned")
    public AjaxResult updateDailyPlanned(@RequestBody GkSetting gkSetting){
        return gkStatisticsService.updateDailyPlanned(gkSetting);
    }

    /**
     * 获取连续NG工件的数量
     * @return
     */
    @GetMapping("/getNgCnt")
    public AjaxResult getNgCnt(){
        List<GkSignalCommunication> list = gkSignalCommunicationService.list(null);
        if (CollUtil.isNotEmpty(list)){
            for (GkSignalCommunication gkSignalCommunication : list) {
                if (gkSignalCommunication.getId().longValue()==24) {
                    BatchReadDTO batchReadDTO = new BatchReadDTO();
                    if (communication.equals("socket")) {
                        try {
                            BufferedWriter bufferedWriter = ScheduledTask.bufferedWriter;
                            BufferedReader bufferedReader = ScheduledTask.bufferedReader;
                            bufferedWriter.write(gkSignalCommunication.getCommunicationProtocol()+"\n");
                            bufferedWriter.flush();
                            String s = bufferedReader.readLine();
                            if (!s.equals("NO")) {
                                JSONArray objects = JSON.parseArray(s);
                                for (Object object : objects) {
                                    SocketDataVo socketDataVo = JSON.parseObject(object.toString(), SocketDataVo.class);
                                    List<ServiceData> nodeList = socketDataVo.getNodeList();
                                    List<NodeDTOV2> nodeDTOV2List = new ArrayList<>();
                                    for (ServiceData serviceData : nodeList) {
                                        NodeDTOV2 nodeDTOV2 = new NodeDTOV2();
                                        nodeDTOV2.setNodeValue(serviceData.getNodeValue());
                                        nodeDTOV2.setNodeId(serviceData.getNodeId());
                                        nodeDTOV2.setNodeType(serviceData.getNodeType());
                                        nodeDTOV2.setNodeName(serviceData.getNodeName());
                                        nodeDTOV2.setDisplayName(serviceData.getDisplayName());
                                        nodeDTOV2List.add(nodeDTOV2);
                                    }
                                    batchReadDTO.setIsConn(true);
                                    batchReadDTO.setUid(socketDataVo.getUid());
                                    batchReadDTO.setDtoList(nodeDTOV2List);
                                }
                            }else {
                                batchReadDTO.setIsConn(false);
                            }
                        } catch (Exception e) {
                            return AjaxResult.error("连续NG工件数量获取异常");
                        }
                    }else {
                        try {
                            OpcUaReadReqV2 opcUaReadReqV2 = new OpcUaReadReqV2();
                            opcUaReadReqV2.setUid(gkSignalCommunication.getCommunicationProtocol());
                            batchReadDTO = opcUaServiceV2.readData(opcUaReadReqV2).getData();
                        } catch (Exception e) {
                            return AjaxResult.error("总成装配线读取异常");
                        }
                    }
                    if (batchReadDTO==null||!batchReadDTO.getIsConn()) {
                        return AjaxResult.error("总成装配线连接异常");
                    }
                    List<NodeDTOV2> dtoList = batchReadDTO.getDtoList();
                    if (CollUtil.isNotEmpty(dtoList)){
                        for (NodeDTOV2 nodeDTOV2 : dtoList) {
                            if (nodeDTOV2.getDisplayName().equals("DB_RECIPE.NG_CNT")) {
                                if (communication.equals("plc")) {
                                    Map<String, Object> map = new HashMap<>();
                                    String value = OpcUATool.getValue(nodeDTOV2);
                                    map.put("nodeValue", value);
                                    return AjaxResult.success(map);
                                }else if (communication.equals("socket")){
                                    Map<String, Object> map = new HashMap<>();
                                    map.put("nodeValue", nodeDTOV2.getNodeValue());
                                    return AjaxResult.success(map);
                                }
                            }
                        }
                    }
                }
            }
        }
        return AjaxResult.error("连续NG工件数量获取失败");
    }

    /**
     * 设置连续NG工件的数量
     * @param nodeDTOV2
     * @return
     */
    @GetMapping("setNgCnt")
    public AjaxResult setNgCnt(NodeDTOV2 nodeDTOV2){
        OpcUaWriteReqV2 opcUaWriteReqV2 = new OpcUaWriteReqV2();
        List<GkSignalCommunication> list = gkSignalCommunicationService.list(null);
        if (CollUtil.isNotEmpty(list)){
            for (GkSignalCommunication gkSignalCommunication : list) {
                if (gkSignalCommunication.getId().longValue()==24){
                    opcUaWriteReqV2.setUid(gkSignalCommunication.getCommunicationProtocol());
                    ArrayList<NodeDTOV2> writeNodeList = new ArrayList<>();
                    nodeDTOV2.setNodeName("DB_RECIPE.NG_CNT");
                    nodeDTOV2.setNodeType("UINT");
                    if (nodeDTOV2.getNodeValue() != null) {
                        nodeDTOV2.setNodeValue(Integer.parseInt(nodeDTOV2.getNodeValue().toString()));
                    }
                    writeNodeList.add(nodeDTOV2);
                    opcUaWriteReqV2.setWriteNodeList(writeNodeList);
                    if (communication.equals("plc")) {
                        try {
                            Ret<List<NodeDTOV2>> listRet = opcUaServiceV2.writeData(opcUaWriteReqV2);
                            log.info("设置属性：{}",JSON.toJSONString(opcUaWriteReqV2.getWriteNodeList()));
                            if (listRet==null){
                                return AjaxResult.error("设置失败,listRet返回null");
                            }
                            log.info("返回属性：{}",JSON.toJSONString(listRet));
                            for (NodeDTOV2 datum : listRet.getData()) {
                                if (datum.getStatusCode()!=0) {
                                    return AjaxResult.error("设置失败");
                                }
                            }
                            return AjaxResult.success("设置成功");
                        } catch (Exception e) {
                            return AjaxResult.error("设置连续NG工件的数量错误");
                        }
                    }else if (communication.equals("socket")){
                        ArrayList<ServiceData> nodeList = new ArrayList<>();
                        for (NodeDTOV2 nodeDTOV21 : writeNodeList) {
                            ServiceData serviceData = new ServiceData();
                            serviceData.setDisplayName(nodeDTOV21.getNodeName());
                            serviceData.setNodeName(nodeDTOV21.getNodeName());
                            serviceData.setNodeValue(nodeDTOV21.getNodeValue());
                            serviceData.setNodeType(nodeDTOV21.getNodeType());
                            nodeList.add(serviceData);
                        }
                        SocketDataVo socketDataVo = new SocketDataVo();
                        socketDataVo.setUid(opcUaWriteReqV2.getUid());
                        socketDataVo.setNodeList(nodeList);
                        try {
                            BufferedWriter bufferedWriter = ScheduledTask.bufferedWriter;
                            BufferedReader bufferedReader = ScheduledTask.bufferedReader;
                            bufferedWriter.write("setData?" + JSON.toJSONString(socketDataVo) + "\n");
                            bufferedWriter.flush();
                            bufferedReader.readLine();
                            return AjaxResult.success();
                        } catch (IOException e) {
                            return AjaxResult.error("设置连续NG工件的数量错误");
                        }
                    }
                }
            }
        }
        return AjaxResult.error();
    }

}
